package com.quick.develop.flowable.service.task.impl;

import cn.hutool.core.collection.CollUtil;
import com.quick.develop.flowable.constant.BpmConstants;
import com.quick.develop.framework.utils.StringUtils;
import com.quick.develop.flowable.application.IBpmTaskAssigneeApplication;
import com.quick.develop.flowable.domain.activity.BpmActivityRespVO;
import com.quick.develop.flowable.framework.convert.task.BpmActivityConvert;
import com.quick.develop.flowable.framework.factory.FlowServiceFactory;
import com.quick.develop.flowable.service.process.IBpmProcessInstanceService;
import com.quick.develop.flowable.service.task.IBpmActivityService;
import com.quick.develop.flowable.service.task.IBpmCommentService;
import com.quick.develop.flowable.service.task.IBpmTaskService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.quick.develop.framework.utils.collection.CollectionUtils.*;

/**
 * @author junyuan.liu
 * @description: 
 * @date 2022/5/2 14:20
 */
@Service
@Slf4j
public class BpmActivityServiceImpl extends FlowServiceFactory implements IBpmActivityService {
    @Resource
    IBpmCommentService bpmCommentService;
    
    @Resource
    IBpmTaskAssigneeApplication bpmTaskAssigneeApplication;
    
    @Resource
    IBpmProcessInstanceService bpmProcessInstanceService;
    
    @Resource
    IBpmTaskService bpmTaskService;
    
    @Override
    public List<BpmActivityRespVO> getHisActivityListByProcessInstanceId(String processInstanceId) {
        if (StringUtils.isEmpty(processInstanceId)) {
            return Collections.emptyList();
        }
        
        List<HistoricActivityInstance> activityList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricActivityInstanceEndTime().desc()
                .list();
        return BpmActivityConvert.INSTANCE.convertList(activityList);
    }

    @Override
    public List<HistoricActivityInstance> getHistoricActivityListByProcessInstanceId(String processInstanceId) {
        if (StringUtils.isEmpty(processInstanceId)) {
            return Collections.emptyList();
        }
        
        return historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricActivityInstanceEndTime().desc()
                .list();
    }

    @Override
    public List<ActivityInstance> getActivityListByProcessInstanceId(String processInstanceId) {
        if (StringUtils.isEmpty(processInstanceId)) {
            return Collections.emptyList();
        }
        return runtimeService.createActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByActivityInstanceEndTime().desc()
                .list();
    }

    @Override
    public Boolean isCallActivityFinished(String processInstanceId) {
        return runtimeService.createActivityInstanceQuery()
                .activityType(BpmConstants.CALL_ACTIVITY)
                .processInstanceId(processInstanceId)
                .unfinished()
                .count() == 0;
    }

    @Override
    public Map<String, List<BpmActivityRespVO>> getBpmViewer(String processInstanceId) {
        List<BpmActivityRespVO> activityList = getHisActivityListByProcessInstanceId(processInstanceId);
        // 子流程 流程实例ID
        Set<String> ids = convertSet(activityList, BpmActivityRespVO::getCalledProcessInstanceId);
        Set<String> users = convertSet(activityList, BpmActivityRespVO::getAssignee);
        // 获得子流程 ProcessInstance Map
        Map<String, HistoricProcessInstance> processInstanceMap = new HashMap<>();
        Map<String, Set<String>> subUsers = new HashMap<>();
        if (!ids.isEmpty()) {
            processInstanceMap = bpmProcessInstanceService.getHistoricProcessInstanceMap(ids);
            // 获取所有子流程运行任务
            List<Task> list = bpmTaskService.getTasksByProcessInstanceIds(ids);
            subUsers = convertMultiMap2(list, Task::getProcessInstanceId, Task::getAssignee);
            Set<String> var = convertSet(list, TaskInfo::getAssignee);
            if (!var.isEmpty()) {
                //合并所有用户
                users.addAll(var);
            }
        }
        // 查找审批人为空 是否为候选任务
        List<BpmActivityRespVO> list = filterList(activityList, i -> StringUtils.isEmpty(i.getAssignee()) && StringUtils.isNotEmpty(i.getTaskId()));
        Map<String, Set<String>> candidateUsers = new HashMap<>();
        if (CollUtil.isNotEmpty(list)) {
            Set<String> taskIds = convertSet(list, BpmActivityRespVO::getTaskId);
            // 有候选组的任务
            Map<String, Set<String>> candidateGroups = bpmTaskService.getCandidateGroups(taskIds);
            candidateUsers = bpmTaskAssigneeApplication.getTaskCandidateUserNameStr(candidateGroups);
        }

        Map<String, String> names = bpmTaskAssigneeApplication.getUsersNameByUserCode(users);
        
        Map<String, List<Comment>> comments = bpmCommentService.getTaskCommentMapByProcessInstanceId(processInstanceId);

        return BpmActivityConvert.INSTANCE.convert1(activityList, processInstanceMap, subUsers, names, candidateUsers, comments);
    }

    @Override
    public List<BpmActivityRespVO> getRunActivityList(String processInstanceId) {
        List<ActivityInstance> list = runtimeService.createActivityInstanceQuery()
                .processInstanceId(processInstanceId).unfinished()
                .list();
        return BpmActivityConvert.INSTANCE.convertList1(list);
    }
}
